package cn.xinfei.xdecision.engine.runner.executor;

import cn.xinfei.xdecision.common.model.component.ComponentVo;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import cn.xinfei.xdecision.engine.runner.executor.strategy.EngineComponentRunner;
import com.dianping.cat.Cat;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tags;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

import static cn.xinfei.xdecision.constant.EngineResultEnum.EXCEPTION_END;
import static cn.xinfei.xdecision.constant.EngineResultEnum.SUCCESS_END;

@Slf4j
public class ComponentHandler  extends AbsNodeHandler<ComponentHandler> {

    private String componentCode;
    private ComponentVo componentVo;

    public ComponentHandler(String nodeType, ComponentVo componentVo) {
        super(nodeType, EngineComponentRunner.PRE);
        this.componentVo = componentVo;
        this.componentCode = componentVo.getCode();
    }


    public StateTransmitModel handler() {
        StateTransmitModel stateTransmitModel =  XDecisionContext.getContext().getStateContext();
        //2.获取节点输入
        Map<String, Object> nodeInput = null;
        try {
            //1.加载变量
            engineNodeRunner.getNodeFieldValue(this);
            //2.获取节点输入
            nodeInput = engineNodeRunner.getNodeInput(this);
            //4.执行节点逻辑
            stateTransmitModel = engineNodeRunner.runNode(this);
        } catch (Exception e) {
            //7.一个节点执行异常，是否继续走后面的节点???
            log.error("节点执行异常,决策流终止，error={}", e.getMessage(), e);
            stateTransmitModel.setFail(e.getMessage());
            Cat.logError(e);
            Metrics.counter("xdecision_error_total", Tags.of("node", nodeType)).increment();
            return stateTransmitModel.setEngineResultEnum(EXCEPTION_END);
        }
        //节点输出，要包含全部的输入输出和过程，凡是作为结果配置的，都进行输出
        //8.获取节点输出
        engineNodeRunner.setNodeOutput(this);
        Map<String, Object> nodeOutput = engineNodeRunner.getNodeOutput(this);

        //10.打印节点日志
        engineNodeRunner.after(this, stateTransmitModel, nodeOutput, nodeInput);
        return stateTransmitModel.setEngineResultEnum(SUCCESS_END);
    }

    @Override
    public String getCode() {
        return componentCode;
    }

    @Override
    public AbsNodeHandler getHandler() {
        return this;
    }

    @Override
    public void push( ) {

    }

    @Override
    public void pop( StateTransmitModel transmitModel) {

    }

    @Override
    public void tracer( ) {

    }

    public String getComponentCode() {
        return componentCode;
    }

    public ComponentVo getComponentVo() {
        return componentVo;
    }
}
